package com.intelligent.system.auth.service.impl;

import cn.hutool.core.bean.BeanUtil;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.intelligent.system.auth.dto.*;

import com.intelligent.system.auth.entity.Role;
import com.intelligent.system.auth.entity.User;
import com.intelligent.system.auth.entity.UserRole;

import com.intelligent.system.auth.mapper.UserMapper;
import com.intelligent.system.auth.mapper.UserRoleMapper;
import com.intelligent.system.auth.service.IRoleService;
import com.intelligent.system.auth.service.IUserService;
import com.intelligent.system.common.exception.CustomException;
import com.intelligent.system.common.response.ResponseCode;
import com.intelligent.system.common.response.ResultDO;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.time.LocalDateTime;

import java.util.List;
import java.util.stream.Collectors;

import com.intelligent.system.auth.dto.StaffInfoDTO;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import com.intelligent.system.common.utils.SnowflakeIdUtils;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Value("${spring.security.oauth2.client.registration.my-auth-server.client-id}")
    private String clientId;

    @Value("${spring.security.oauth2.client.registration.my-auth-server.client-secret}")
    private String clientSecret;

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private IRoleService roleService;

    @Resource
    private OAuth2AuthorizedClientService clientService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private SnowflakeIdUtils idUtils;

    public ResultDO<UserDTO> getUserByUsername(String username) {
        log.info("请求参数:{}", username);
        User user;
        try {
            user = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                    .eq(User::getLoginName, username)
                    .eq(User::getStatus, 0)
                    .eq(User::getIsDelete, 0));
        } catch (Exception e) {
            log.error("通过用户名查询用户出现异常", e);
            throw new CustomException("通过用户名查询用户异常", ResponseCode.INTERNAL_SERVER_ERROR.getCode());
        }
        UserDTO dto = new UserDTO();
        BeanUtil.copyProperties(user, dto);
        return ResultDO.success(dto);
    }

    @Override
    public ResultDO<UserDTO> getUserById(Long id) {
        try {
            // 1. 获取用户基本信息
            User user = this.getById(id);
            if (user == null) {
                log.error("未找到ID为 {} 的用户", id);
                throw new CustomException("用户不存在", ResponseCode.USER_NOT_FOUND.getCode());
            }
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(user, userDTO);

            // 2. 获取用户的角色关联信息
            List<UserRole> userRoles = userRoleMapper.selectList(
                    Wrappers.<UserRole>lambdaQuery()
                            .eq(UserRole::getUserId, id)
            );

            // 3. 如果存在角色关联，获取完整的角色信息
            if (userRoles != null && !userRoles.isEmpty()) {
                // 提取角色ID列表
                List<Long> roleIds = userRoles.stream()
                        .map(UserRole::getRoleId)
                        .collect(Collectors.toList());

                // 获取完整的角色信息
                List<Role> roles = roleService.listByIds(roleIds);

                // 转换为DTO对象
                List<RoleDTO> roleDTOs = roles.stream()
                        .map(role -> {
                            RoleDTO roleDTO = new RoleDTO();
                            BeanUtils.copyProperties(role, roleDTO);
                            return roleDTO;
                        })
                        .collect(Collectors.toList());

                // 在用户DTO中设置角色ID列表和角色DTO列表
                userDTO.setRoleList(roleDTOs);
                userDTO.setRoleIds(roleIds);
            }

            return ResultDO.success(userDTO);
        } catch (Exception e) {
            log.error("获取用户失败，ID: {}", id, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    public ResultDO<?> getUserList(UserQueryDTO param) {
        try {
            Page<User> page = new Page<>(param.getPageNum(), param.getPageSize());
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            
            // 添加查询条件
            if (StringUtils.hasText(param.getLoginName())) {
                wrapper.like(User::getLoginName, param.getLoginName());
            }
            if (StringUtils.hasText(param.getUserType())) {
                wrapper.eq(User::getUserType, param.getUserType());
            }
            if (param.getStatus() != null) {
                wrapper.eq(User::getStatus, param.getStatus());
            }
            
            // 执行分页查询
            Page<User> resultPage = this.page(page, wrapper);
            
            // 转换为DTO
            Page<UserDTO> dtoPage = new Page<>();
            BeanUtils.copyProperties(resultPage, dtoPage, "records");
            List<UserDTO> dtoList = resultPage.getRecords().stream()
                    .map(user -> {
                        UserDTO dto = new UserDTO();
                        BeanUtils.copyProperties(user, dto);
                        return dto;
                    })
                    .collect(Collectors.toList());
            dtoPage.setRecords(dtoList);
            
            return ResultDO.success(dtoPage);
        } catch (Exception e) {
            log.error("获取用户列表失败，参数: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> addUser(UserDTO param) {
        try {
            // 检查用户名是否已存在
            if (this.checkLoginNameExists(param.getLoginName())) {
                log.error("登录名已存在: {}", param.getLoginName());
                throw new CustomException("用户名已存在", ResponseCode.USER_ALREADY_EXISTS.getCode());
            }

            // 保存用户基本信息
            User user = new User();
            BeanUtils.copyProperties(param, user);
            user.setUserId(idUtils.nextId());
            if (!this.save(user)) {
                throw new CustomException("保存用户失败", ResponseCode.SYSTEM_ERROR.getCode());
            }

            // 保存用户-角色关联关系
            if (param.getRoleIds() != null && !param.getRoleIds().isEmpty()) {
                List<UserRole> userRoles = param.getRoleIds().stream()
                    .map(roleId -> {
                        UserRole userRole = new UserRole();
                        userRole.setId(idUtils.nextId());
                        userRole.setUserId(user.getUserId());
                        userRole.setRoleId(roleId);
                        return userRole;
                    })
                    .collect(Collectors.toList());

                // 批量保存用户-角色关联
                for (UserRole userRole : userRoles) {
                    if (userRoleMapper.insert(userRole) <= 0) {
                        throw new CustomException("保存用户角色关联失败", ResponseCode.SYSTEM_ERROR.getCode());
                    }
                }
            }

            return ResultDO.success(null);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("添加用户失败: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> updateUser(UserDTO param) {
        try {
            User user = this.getById(param.getUserId());
            if (user == null) {
                log.error("未找到ID为 {} 的用户", param.getUserId());
                throw new CustomException("用户不存在", ResponseCode.USER_NOT_FOUND.getCode());
            }

            // 如果修改了登录名，需要检查是否已存在
            if (!user.getLoginName().equals(param.getLoginName()) 
                    && this.checkLoginNameExists(param.getLoginName())) {
                log.error("登录名已存在: {}", param.getLoginName());
                throw new CustomException("用户名已存在", ResponseCode.USER_ALREADY_EXISTS.getCode());
            }

            BeanUtils.copyProperties(param, user);
            if (this.updateById(user)) {
                // 更新用户角色关联
                if (param.getRoleIds() != null) {
                    // 删除用户现有的所有角色关联
                    userRoleMapper.delete(Wrappers.<UserRole>lambdaQuery()
                            .eq(UserRole::getUserId, user.getUserId()));

                    // 如果有新的角色需要关联
                    if (!param.getRoleIds().isEmpty()) {
                        // 构建新的角色关联列表
                        List<UserRole> userRoles = param.getRoleIds().stream()
                                .map(roleId -> {
                                    UserRole userRole = new UserRole();
                                    userRole.setId(idUtils.nextId());
                                    userRole.setUserId(user.getUserId());
                                    userRole.setRoleId(roleId);
                                    return userRole;
                                })
                                .collect(Collectors.toList());

                        // 批量保存新的角色关联
                        for (UserRole userRole : userRoles) {
                            if (userRoleMapper.insert(userRole) <= 0) {
                                throw new CustomException("更新用户角色关联失败", ResponseCode.SYSTEM_ERROR.getCode());
                            }
                        }
                    }
                }
                return ResultDO.success(null);
            }
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新用户失败: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> updateUserStatus(Long userId, Byte status) {
        try {
            User user = this.getById(userId);
            if (user == null) {
                log.error("未找到ID为 {} 的用户", userId);
                throw new CustomException("用户不存在", ResponseCode.USER_NOT_FOUND.getCode());
            }

            user.setStatus(status);
            if (this.updateById(user)) {
                return ResultDO.success(null);
            }
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新用户状态失败: userId={}, status={}", userId, status, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> deleteUserById(Long userId) {
        try {
            if (!this.removeById(userId)) {
                log.error("删除用户失败: {}", userId);
                throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
            }
            return ResultDO.success(null);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("删除用户失败: {}", userId, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> assignRole(Long userId, List<Long> roleIds) {
        try {
            // 检查用户是否存在
            if (!this.checkUserExists(userId)) {
                log.error("未找到ID为 {} 的用户", userId);
                throw new CustomException("用户不存在", ResponseCode.USER_NOT_FOUND.getCode());
            }

            // TODO: 实现角色分配逻辑
            return ResultDO.success(null);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("分配角色失败: userId={}, roleIds={}", userId, roleIds, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    private boolean checkLoginNameExists(String loginName) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getLoginName, loginName);
        return this.count(wrapper) > 0;
    }

    private boolean checkUserExists(Long userId) {
        return this.getById(userId) != null;
    }

    @Override
    public ResultDO<?> register(Authentication authentication) {
        if (authentication instanceof OAuth2AuthenticationToken) {
            OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
            String clientRegistrationId = oauthToken.getAuthorizedClientRegistrationId();
            String username = oauthToken.getName();
            OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(clientRegistrationId, username);
            if (client != null) {
                try {
                    String userInfoUri = "http://183.66.216.10:88/oauth/staff_detail";
                    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(userInfoUri)
                            .queryParam("client_id", clientId)
                            .queryParam("client_secret", clientSecret);

                    ResponseEntity<ResultDO<StaffInfoDTO>> userInfoResponse = restTemplate.exchange(
                            builder.build().toUri(),
                            HttpMethod.GET,
                            null,
                            new ParameterizedTypeReference<ResultDO<StaffInfoDTO>>() {}
                    );

                    if (userInfoResponse.getStatusCode() == HttpStatus.OK && userInfoResponse.getBody() != null) {
                        ResultDO<StaffInfoDTO> result = userInfoResponse.getBody();

                        if (result.getCode() == 200 && result.getData() != null) {
                            StaffInfoDTO staffInfo = result.getData();
                            // 创建或更新用户
                            UserDTO userDTO = createOrUpdateUser(staffInfo);
                            return ResultDO.success("用户注册成功");
                        } else {
                            log.error("OAuth2用户信息获取失败: code={}", result.getCode());
                            throw new CustomException("用户信息获取失败", ResponseCode.INTERNAL_SERVER_ERROR.getCode());
                        }
                    }
                } catch (RestClientException e) {
                    log.error("OAuth2用户信息获取异常: {}", e.getMessage(), e);
                    throw new CustomException("用户信息获取失败", ResponseCode.INTERNAL_SERVER_ERROR.getCode());
                }
            }
        }
        return ResultDO.success("添加成功");
    }

    private boolean isValidPassword(String password) {
        if (!StringUtils.hasText(password)) {
            return false;
        }
        String pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,20}$";
        return password.matches(pattern);
    }

    @Override
    public UserDTO createOrUpdateUser(StaffInfoDTO staffInfoDTO) {
        try {
            User user = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                .eq(User::getUserId, staffInfoDTO.getStaffId())
                .eq(User::getIsDelete, 0));
            boolean isNew = (user == null);
            if (isNew) {
                user = new User();
                user.setUserId(Long.valueOf(staffInfoDTO.getStaffId()));
                user.setCreateTime(LocalDateTime.now());
                user.setIsDelete((byte) 0);
            }
            user.setLoginName(staffInfoDTO.getUsername());
            user.setStatus(staffInfoDTO.getStatus() == null ? 1 : staffInfoDTO.getStatus().byteValue());
            user.setUpdateTime(LocalDateTime.now());
            if (isNew) {
                userMapper.insert(user);
            } else {
                userMapper.updateById(user);
            }
            UserDTO userDTO = new UserDTO();
            BeanUtil.copyProperties(user, userDTO);
            return userDTO;
        } catch (Exception e) {
            log.error("创建或更新用户异常: {}", e.getMessage(), e);
            throw new CustomException("创建或更新用户失败", ResponseCode.INTERNAL_SERVER_ERROR.getCode());
        }
    }
}
